﻿using JNPF.Basics.Models;
using JNPF.Data;
using JNPF.Data.Util;
using JNPF.Utils;
using JNPF.Utils.Quartz;
using Quartz;
using Quartz.Spi;
using System;
using System.Collections;
using System.Collections.Generic;
using System.Text;

namespace JNPF.Basics.Logic
{
    /// <summary>
    /// CronUtil
    /// </summary>
    public class CronUtil : DataFactory
    {

        private readonly IJobFactory _iocjobFactory;

        public CronUtil(IJobFactory jobFactory)
        {
            _iocjobFactory = jobFactory;
        }
        public CronUtil()
        {
        }

        /// <summary>
        /// 静态实例
        /// </summary>
        public static CronUtil Instance
        {
            get { return new CronUtil(); }
        }
        /// <summary>
        /// 获取多个表达式
        /// </summary>
        /// <param name="model">页面模型</param>
        /// <returns></returns>
        public List<string> GetMoreCron(ContentModel model)
        {
            var cron = new List<string>();
            if (model.frequency == "3")
            {
                foreach (var item in model.frequencyList)
                {
                    StringBuilder builder = new StringBuilder();
                    StringBuilder second = new StringBuilder("*");
                    StringBuilder hours = new StringBuilder();
                    StringBuilder minute = new StringBuilder();
                    StringBuilder week = new StringBuilder();
                    StringBuilder day = new StringBuilder();
                    StringBuilder mounth = new StringBuilder();
                    if (item.Type == "1")
                    {
                        day.Append("*");
                        week.Append("?");
                    }
                    else if (item.Type == "2")
                    {
                        day.Append("?");
                        week.Append(item.Week);
                    }
                    else if (item.Type == "3")
                    {
                        day.Append(item.Day);
                        week.Append("?");
                    }
                    hours.Append(item.Hours);
                    minute.Append(item.Minute);
                    mounth.Append(item.Month);
                    builder.Append(second + " " + minute + " " + hours + " " + day + " " + mounth + " " + week);
                    cron.Add(builder.ToString());

                }
            }
            return cron;
        }
        /// <summary>
        /// 设置cron表达式
        /// </summary>
        /// <param name="contentModel">页面模型</param>
        /// <param name="cycle">表达式</param>
        /// <returns></returns>
        public string GetOneCron(ContentModel contentModel, string cycle)
        {
            var cron = "";
            if (contentModel.frequency == "2")
            {
                StringBuilder builder = new StringBuilder();
                StringBuilder second = new StringBuilder();
                StringBuilder minute = new StringBuilder();
                StringBuilder hours = new StringBuilder();
                StringBuilder day = new StringBuilder();
                StringBuilder mounth = new StringBuilder();
                StringBuilder week = new StringBuilder();
                second.Append(contentModel.seconds != "" ? contentModel.seconds : "*");
                hours.Append(contentModel.hours != "" ? contentModel.hours : "*");
                minute.Append(contentModel.minute != "" ? contentModel.minute : "*");
                mounth.Append(contentModel.month != "" ? contentModel.month : "*");
                if (contentModel.type == "1")
                {
                    day.Append(contentModel.day != "" ? contentModel.day : "*");
                    week.Append("?");
                }
                else if (contentModel.type == "2")
                {
                    day.Append("?");
                    week.Append(contentModel.week != "" ? contentModel.week : "*");
                }
                builder.Append(second + " " + minute + " " + hours + " " + day + " " + mounth + " " + week);
                cron = builder.ToString();
            }
            else if (contentModel.frequency == "4")
            {
                cron = contentModel.frequency;
            }
            return cron;
        }
        /// <summary>
        /// 添加任务
        /// </summary>
        /// <param name="entity">实体</param>
        /// <param name="model">页面模型</param>
        /// <param name="tenantId">租户Id</param>
        public async void StartJobAsync(TimeTaskEntity entity, ContentModel model, string tenantId)
        {
            var schedulercenterserver = new SchedulerCenterServer(_iocjobFactory);
            IDictionary<string, object> dic = new Dictionary<string, object>();
            JobKey jobKey = new JobKey(entity.FullName, entity.EnCode);
            dic.Add("data", entity);
            dic.Add("content", model);


            if (entity.EnabledMark == 1)
            {
                if (model.start == "1")
                {
                    dic["type"] = 1;
                    JobDataMap dataMap = new JobDataMap(dic);
                    //1.判断执行次数
                    if (model.frequency == "1")
                    {
                        if (entity.ExecuteType == "2")
                        {
                            Storage(model, entity, tenantId);
                        }
                        else if (entity.ExecuteType == "1")
                        {
                            Connector(model, entity, tenantId);
                        }
                    }
                    else if (model.frequency == "2")
                    {
                        var trigger = TriggerBuilder.Create()
                         .WithDescription(entity.Description)
                         .WithIdentity(entity.FullName, tenantId)
                         .WithSchedule(CronScheduleBuilder.CronSchedule(entity.ExecuteCycleJson))
                         .EndAt(entity.LastRunTime)//结束时间
                         .Build();
                        await schedulercenterserver.AddScheduleJobAsync(typeof(MyJob), jobKey, dataMap, trigger);
                    }
                    else if (model.frequency == "3")
                    {
                        string[] cycle = entity.ExecuteCycleJson.Split(";");
                        for (int i = 0; i < cycle.Length; i++)
                        {
                            var cron = cycle[i];
                            var trigger = TriggerBuilder.Create()
                                 .WithDescription(entity.Description)
                                 .WithIdentity(entity.FullName, tenantId + "-" + i)
                                 .WithSchedule(CronScheduleBuilder.CronSchedule(cron))
                                 .EndAt(entity.LastRunTime)//结束时间
                                 .Build();
                            await schedulercenterserver.AddScheduleJobAsync(typeof(MyJob), jobKey, dataMap, trigger);
                        }
                    }
                    else if (model.frequency == "4")
                    {
                        var trigger = TriggerBuilder.Create()
                             .WithDescription(entity.Description)
                             .WithIdentity(entity.FullName, tenantId)
                             .WithSchedule(CronScheduleBuilder.CronSchedule(entity.ExecuteCycleJson))
                             .EndAt(entity.LastRunTime)//结束时间
                             .Build();
                        await schedulercenterserver.AddScheduleJobAsync(typeof(MyJob), jobKey, dataMap, trigger);
                    }
                }
                else if (model.start == "2")
                {
                    dic["type"] = 2;
                    JobDataMap dataMap = new JobDataMap(dic);
                    var trigger = TriggerBuilder.Create()
                         .WithDescription(entity.Description)
                         .WithIdentity(entity.FullName, tenantId)
                         .WithSchedule(CronScheduleBuilder.CronSchedule(entity.ExecuteCycleJson))
                         .StartAt(new DateTime())
                         .EndAt(entity.LastRunTime)//结束时间
                         .Build();
                    await schedulercenterserver.AddScheduleJobAsync(typeof(MyJob), jobKey, dataMap, trigger);
                }
                if (model.end == "2" && model.frequency != "1")
                {
                    dic["type"] = 3;
                    JobDataMap dataMap = new JobDataMap(dic);
                    if (model.frequency == "3")
                    {
                        string[] cycle = entity.ExecuteCycleJson.Split(";");
                        for (int i = 0; i < cycle.Length; i++)
                        {
                            var cron = cycle[i];
                            var trigger = TriggerBuilder.Create()
                                 .WithDescription(entity.Description)
                                 .WithIdentity(entity.FullName, tenantId + "-" + i)
                                 .WithSchedule(CronScheduleBuilder.CronSchedule(cron))
                                 .EndAt(entity.LastRunTime)//结束时间
                                 .Build();
                            await schedulercenterserver.AddScheduleJobAsync(typeof(MyJob), jobKey, dataMap, trigger);
                        }
                    }
                    else
                    {
                        var trigger = TriggerBuilder.Create()
                             .WithDescription(entity.Description)
                             .WithIdentity(entity.FullName, tenantId)
                             .WithSchedule(CronScheduleBuilder.CronSchedule(entity.ExecuteCycleJson))
                             .EndAt(entity.LastRunTime)//结束时间
                             .Build();
                        await schedulercenterserver.AddScheduleJobAsync(typeof(MyJob), jobKey, dataMap, trigger);
                    }
                }
            }
        }
        /// <summary>
        /// 存储过程
        /// </summary>
        /// <param name="model">页面模型</param>
        /// <param name="entity">实体</param>
        /// <param name="tenantId">租户Id</param>
        public void Storage(ContentModel model, TimeTaskEntity entity, string tenantId)
        {
            try
            {
                var sql = new StringBuilder();
                sql.Append("EXEC " + model.stored + " ");
                foreach (var item in model.storedParameter)
                {
                    var key = item.Key;
                    var value = item.Value;
                    sql.Append("@" + key + "='" + value + "',");
                }
                if (sql.Length > 0)
                {
                    sql.Remove(sql.Length - 1, 1);
                }
                var dbConnString = ConfigurationHelper.GetDbConnection("JNPF_DB_Default:ConnectionString");
                var dbType = ConfigurationHelper.GetDbConnection("JNPF_DB_Default:ConnectionType").ToDatabaseType();
                var db = this.Data(dbConnString, dbType);
                int all = 0;
                if (db != null)
                {
                    all = db.ExecuteSql(sql.ToString());
                }
                using (var dbt = this.Basic)
                {
                    StringBuilder log = new StringBuilder();
                    log.Append("insert into BASE_TIMETASKLOG(F_Id,F_TaskId,F_RunTime,F_RunResult,F_Description) VALUES");
                    log.Append("('" + CommonHelper.Guid + "', ");
                    log.Append("'" + entity.Id + "', ");
                    log.Append("'" + DateTime.Now + "', ");
                    if (all == 0)
                    {
                        log.Append("'1','存储过程调用失败')");
                    }
                    else
                    {
                        log.Append("'0','存储过程调用成功')");
                    }
                    dbt.ExecuteSql(log.ToString());
                    var update = "UPDATE BASE_TIMETASK SET F_RUNCOUNT=(SELECT F_RUNCOUNT FROM BASE_TIMETASK WHERE F_ID='" + entity.Id + "')+1,F_NextRunTime='" + DateTime.Now + "' where F_ID='" + entity.Id + "'";
                    dbt.ExecuteSql(update.ToString());
                }
            }
            catch (Exception)
            {
            }
        }
        /// <summary>
        /// 接口
        /// </summary>
        /// <param name="model">页面模型</param>
        /// <param name="entity">实体</param>
        /// <param name="tenantId">租户Id</param>
        public void Connector(ContentModel model, TimeTaskEntity entity, string tenantId)
        {
            try
            {
                var res = "";
                if (model.interfaceType.ToLower() == "get")
                {
                    Hashtable hashtable = new Hashtable();
                    foreach (var item in model.parameter)
                    {
                        hashtable.Add(item.Key, item.Value);
                    }
                    res = HttpMethods.HttpGet(model.interfaceUrl, hashtable);
                }
                else if (model.interfaceType.ToLower() == "post")
                {
                    StringBuilder postData = new StringBuilder();
                    if (model.parameter != null)
                    {

                        for (int i = 0; i < model.parameter.Count; i++)
                        {
                            if (i == 0)
                            {
                                postData.Append("" + "?" + model.parameter[i].Key + "=" + model.parameter[i].Value + "");
                            }
                            else
                            {
                                postData.Append("" + "&" + model.parameter[i].Key + "=" + model.parameter[i].Value + "");
                            }
                        }
                    }
                    res = HttpMethods.HttpPost(model.interfaceUrl, postData.ToString());
                }
                StringBuilder sql = new StringBuilder();
                sql.Append("INSERT INTO BASE_TIMETASKLOG(F_Id,F_TaskId,F_RunTime,F_RunResult,F_Description) VALUES");
                sql.Append("('" + CommonHelper.Guid + "', ");
                sql.Append("'" + entity.Id + "', ");
                sql.Append("'" + DateTime.Now + "', ");
                if (res.IsNullOrEmpty())
                {
                    sql.Append("'" + 1 + "', ");
                    sql.Append("'接口不存在或请求错误') ");
                }
                else
                {
                    sql.Append("'" + 0 + "', ");
                    sql.Append("'') ");
                }
                TimeTaskLogEntity logEntity = new TimeTaskLogEntity();
                logEntity.Id = CommonHelper.Guid;
                logEntity.TaskId = entity.Id;
                logEntity.RunTime = DateTime.Now;
                var dbConnString = ConfigurationHelper.GetDbConnection("JNPF_DB_Default:ConnectionString");
                var dbType = ConfigurationHelper.GetDbConnection("JNPF_DB_Default:ConnectionType").ToDatabaseType();
                var db = this.Data(dbConnString, dbType);
                db.ExecuteSql(sql.ToString());
                using (var dbt = this.Basic)
                {
                    var update = "UPDATE BASE_TIMETASK SET F_RUNCOUNT=(SELECT F_RUNCOUNT FROM BASE_TIMETASK WHERE F_ID='" + entity.Id + "')+1,F_NextRunTime='" + DateTime.Now + "' where F_ID='" + entity.Id + "'";
                    dbt.ExecuteSql(update.ToString());
                }
            }
            catch (Exception e)
            {
                LogFactory.GetLogger().Error(e);
            }
        }
        /// <summary>
        /// 停止
        /// </summary>
        /// <param name="entity">实体</param>
        public async void Remove(TimeTaskEntity entity)
        {
            var schedulercenterserver = new SchedulerCenterServer(_iocjobFactory);
            var jobKey = new JobKey(entity.FullName, entity.EnCode);
            await schedulercenterserver.StopScheduleJobAsync(jobKey);
        }
    }
}
